package jp.android_group.attender.android.entity;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

/*
 * Copyright (c) 2009, "Japan Android Group Attender Team"
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * 出席者情報のモデル
 * 
 */
public class Attendee {
	private static final String LOG_TAG = "Attendee";
	private static final boolean DEBUG_FLG = true;

	public static final int ATTEND_FLG_NOT_SET = 0;
	public static final int ATTEND_FLG_ATTEND = 1;
	public static final int ATTEND_FLG_REGISTERED = 2;
	public static final int ATTEND_FLG_CANCELED = -1;

	private int id = -1;
	private int eventId = -1;
	private String attendeeCode = null;
	private String name = null;
	private String mailAddress = null;
	private String number = null;
	private int attendFlg = ATTEND_FLG_NOT_SET;
	private String comment = null;

	private static final String TABLE_NAME = "m_attendee";
	private static final String[] projection = new String[] { "_id",
			"event_id", "attendee_code", "name", "mail_address", "number",
			"attend_flag", "comment" };

	/**
	 * 参加者テーブルを作成
	 * 
	 * @param db
	 */
	public static void createTable(SQLiteDatabase db) {
		StringBuilder sql = new StringBuilder();
		sql.append("CREATE TABLE " + TABLE_NAME);
		sql.append(" (");
		sql.append("_id INTEGER PRIMARY KEY, ");
		sql.append("event_id INTEGER, ");
		sql.append("attendee_code TEXT, ");
		sql.append("name TEXT, ");
		sql.append("mail_address TEXT, ");
		sql.append("number INTEGER, ");
		sql.append("attend_flag INTEGER, ");
		sql.append("comment TEXT ");
		sql.append(")");
		db.execSQL(sql.toString());
	}

	/**
	 * インデックスの作成
	 * 
	 * @param db
	 */
	public static void createIndex(SQLiteDatabase db) {
		db
				.execSQL("CREATE INDEX m_attendee_index ON m_attendee(event_id, attendee_code)");
	}

	/**
	 * 参加者テーブルを破棄
	 * 
	 * @param db
	 */
	public static void dropTable(SQLiteDatabase db) {
		StringBuilder sql = new StringBuilder();
		sql.append("DROP TABLE " + TABLE_NAME);
		db.execSQL(sql.toString());
	}

	/**
	 * DBに保存
	 * 
	 * @param data
	 * @param db
	 */
	public static void save(Attendee data, SQLiteDatabase db) {
		ContentValues values = new ContentValues();
		values.put("event_id", data.getEventId());
		values.put("attendee_code", data.getAttendeeCode());
		values.put("number", data.getNumber());
		values.put("name", data.getName());
		values.put("mail_address", data.getMailAddress());
		values.put("attend_flag", data.getAttendFlg());
		values.put("comment", data.getComment());

		boolean existFlg = false;
		Collection<Attendee> list = load(data.getEventId(), data
				.getAttendeeCode(), db);
		if (list.size() > 0)
			existFlg = true;

		if (existFlg == false) {
			db.insert(TABLE_NAME, null, values);
		} else {

			if (data.getAttendFlg() == Attendee.ATTEND_FLG_ATTEND
					|| data.getAttendFlg() == Attendee.ATTEND_FLG_REGISTERED
					|| data.getAttendFlg() == Attendee.ATTEND_FLG_CANCELED) {
				db.update(TABLE_NAME, values,
						"event_id = ? AND attendee_code = ?", new String[] {
								String.valueOf(data.getEventId()),
								String.valueOf(data.getAttendeeCode()) });
			}

			if (DEBUG_FLG)
				Log.v(LOG_TAG, "insert is failed. target data is updated");
		}
	}

	/**
	 * 参加フラグを解除
	 * 
	 * @param db
	 */
	public void revertAttend(SQLiteDatabase db) {
		revertAttend(this, db);
	}

	/**
	 * 参加フラグを解除
	 * 
	 * @param data
	 * @param db
	 */
	public static void revertAttend(Attendee data, SQLiteDatabase db) {
		ContentValues values = new ContentValues();
		values.put("event_id", data.getEventId());
		values.put("attendee_code", data.getAttendeeCode());
		values.put("number", data.getNumber());
		values.put("name", data.getName());
		values.put("mail_address", data.getMailAddress());
		values.put("attend_flag", data.getAttendFlg());
		values.put("comment", data.getComment());

		boolean existFlg = false;
		Collection<Attendee> list = load(data.getEventId(), data
				.getAttendeeCode(), db);
		if (list.size() > 0)
			existFlg = true;

		if (existFlg == true) {
			if (data.getAttendFlg() == Attendee.ATTEND_FLG_NOT_SET) {
				db.update(TABLE_NAME, values,
						"event_id = ? AND attendee_code = ?", new String[] {
								String.valueOf(data.getEventId()),
								String.valueOf(data.getAttendeeCode()) });
			}

			if (DEBUG_FLG)
				Log.v(LOG_TAG, "insert is failed. target data is updated");
		}
	}

	public static final int ORDER_ID_ASC = 0;
	public static final int ORDER_ID_DESC = 1;
	public static final int ORDER_NAME_ASC = 2;
	public static final int ORDER_NAME_DESC = 3;
	public static final int ORDER_MAIL_ADDRESS_ASC = 4;
	public static final int ORDER_MAIL_ADDRESS_DESC = 5;

	/**
	 * DBを読込み
	 * 
	 * @param db
	 * @return
	 */
	public static Cursor loadCursor(SQLiteDatabase db, Event event,
			Filter filter, int comp) {

		String selection = null;
		String[] selectionArgs = null;
		String mailAddress = filter.getEmail();
		if (mailAddress != null && mailAddress.equals("") == false) {
			selection = "event_id = ? AND mail_address LIKE ?";
			selectionArgs = new String[] { String.valueOf(event.getId()),
					mailAddress + "%" };
		} else {
			selection = "event_id = ?";
			selectionArgs = new String[] { String.valueOf(event.getId()) };
		}

		return db.query(TABLE_NAME, projection, selection, selectionArgs, null,
				null, getOrderString(comp));
	}

	/**
	 * 
	 * @param comp
	 * @return
	 */
	private static String getOrderString(int comp) {

		switch (comp) {
		case ORDER_ID_ASC:
			return "_id asc";
		case ORDER_ID_DESC:
			return "_id desc";
		case ORDER_NAME_ASC:
			return "name asc";
		case ORDER_NAME_DESC:
			return "name desc";
		case ORDER_MAIL_ADDRESS_ASC:
			return "mail_address asc";
		case ORDER_MAIL_ADDRESS_DESC:
			return "mail_address desc";
		}
		;
		return null;
	}

	public static class Filter {
		private String email = null;

		/**
		 * @param email
		 *            the email to set
		 */
		public void setEmail(String email) {
			this.email = email;
		}

		/**
		 * @return the email
		 */
		public String getEmail() {
			return email;
		}

		/**
		 * 
		 * @param data
		 * @return
		 */
		private boolean exec(Attendee data) {
			if (email == null)
				return true;
			if (data.getMailAddress().indexOf(email) == -1)
				return false;

			return true;
		}
	}

	/**
	 * 出席で、サーバーに送信されていない参加者データを検索
	 * 
	 * @param db
	 * @return
	 */
	public static Cursor loadAttendeeCursor(SQLiteDatabase db, Event event) {

		return db.query(TABLE_NAME, projection,
				"event_id = ? AND attend_flag == ?", new String[] {
						String.valueOf(event.getId()),
						String.valueOf(ATTEND_FLG_ATTEND) }, null, null,
				"_id desc");
	}

	/**
	 * @deprecated DBを読込み
	 * @param db
	 * @return
	 */
	public static Collection<Attendee> load(SQLiteDatabase db) {
		LinkedList<Attendee> list = new LinkedList<Attendee>();
		Cursor cursor = db.query(TABLE_NAME, projection, "_id > ?",
				new String[] { "0" }, null, null, "_id desc");

		if (cursor.moveToFirst()) {
			do {
				list.add(fetchData(cursor));
			} while (cursor.moveToNext());
		}

		cursor.close();

		return list;
	}

	/**
	 * 参加者コード（ＱＲコードの値）に該当する参加者を取得
	 * 
	 * @param event
	 * @param attendeeId
	 * @return
	 */
	public static Attendee findByAttendeeId(Event event, String attendeeCode,
			SQLiteDatabase db) {

		Attendee result = null;
		Cursor cursor = db.query(TABLE_NAME, projection,
				"event_id = ? AND attendee_code = ?", new String[] {
						String.valueOf(event.getId()), attendeeCode }, null,
				null, "_id desc");
		if (cursor.moveToNext()) {
			result = new Attendee();
			fetchData(cursor, result);
		}
		return result;
	}

	/**
	 * @deprecated ＤＢを読込み
	 * @param db
	 * @return
	 */
	public static HashMap<String, Attendee> load(int eventId, SQLiteDatabase db) {
		HashMap<String, Attendee> list = new HashMap<String, Attendee>();
		Cursor cursor = db.query(TABLE_NAME, projection, "event_id = ?",
				new String[] { String.valueOf(eventId) }, null, null,
				"_id desc");

		if (cursor.moveToFirst()) {
			do {
				Attendee data = fetchData(cursor);
				list.put(data.getAttendeeCode(), data);
			} while (cursor.moveToNext());
		}

		cursor.close();

		return list;
	}

	/**
	 * @deprecated ＤＢを読込み
	 * @param db
	 * @return
	 */
	public static Collection<Attendee> load(int eventId, String attendeeCode,
			SQLiteDatabase db) {
		LinkedList<Attendee> list = new LinkedList<Attendee>();
		Cursor cursor = db.query(TABLE_NAME, projection,
				"event_id = ? AND attendee_code = ?",
				new String[] { String.valueOf(eventId),
						String.valueOf(attendeeCode) }, null, null, "_id desc");

		if (cursor.moveToFirst()) {
			do {
				list.add(fetchData(cursor));
			} while (cursor.moveToNext());
		}

		cursor.close();

		return list;
	}

	public static final int COLUMN_ID = 0;
	public static final int COLUMN_EVENT_ID = 1;
	public static final int COLUMN_ATTENDEE_CODE = 2;
	public static final int COLUMN_NAME = 3;
	public static final int COLUMN_MAIL_ADDRESS = 4;
	public static final int COLUMN_NUMBER = 5;
	public static final int COLUMN_ATTEND_FLAG = 6;
	public static final int COLUMN_COMMENT = 7;

	/**
	 * @deprecated データのフェッチ
	 * @param cursor
	 * @return
	 */
	public static Attendee fetchData(Cursor cursor) {

		Attendee data = new Attendee();
		fetchData(cursor, data);
		return data;
	}

	/**
	 * データのフェッチ
	 * 
	 * @param cursor
	 * @param data
	 */
	public static void fetchData(Cursor cursor, Attendee data) {

		data.setId(cursor.getInt(COLUMN_ID));
		data.setEventId(cursor.getInt(COLUMN_EVENT_ID));
		data.setAttendeeCode(cursor.getString(COLUMN_ATTENDEE_CODE));
		data.setNumber(cursor.getString(COLUMN_NUMBER));
		data.setName(cursor.getString(COLUMN_NAME));
		data.setMailAddress(cursor.getString(COLUMN_MAIL_ADDRESS));
		data.setAttendFlg(cursor.getInt(COLUMN_ATTEND_FLAG));
		data.setComment(cursor.getString(COLUMN_COMMENT));
	}

	/*
	 * setter and getter
	 */

	/**
	 * @param _id
	 *            the _id to set
	 */
	public void setId(int _id) {
		this.id = _id;
	}

	/**
	 * @return the _id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @param _event_id
	 *            the _event_id to set
	 */
	public void setEventId(int _event_id) {
		this.eventId = _event_id;
	}

	/**
	 * @return the _event_id
	 */
	public int getEventId() {
		return eventId;
	}

	/**
	 * @param _attendeeCode
	 *            the _attendeeCode to set
	 */
	public void setAttendeeCode(String _attendeeCode) {
		this.attendeeCode = _attendeeCode;
	}

	/**
	 * @return the _attendeeCode
	 */
	public String getAttendeeCode() {
		return attendeeCode;
	}

	/**
	 * @param _name
	 *            the _name to set
	 */
	public void setName(String _name) {
		this.name = _name;
	}

	/**
	 * @return the _name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param _mailAddress
	 *            the _mailAddress to set
	 */
	public void setMailAddress(String _mailAddress) {
		this.mailAddress = _mailAddress;
	}

	/**
	 * @return the _mailAddress
	 */
	public String getMailAddress() {
		return mailAddress;
	}

	/**
	 * @param _number
	 *            the _number to set
	 */
	public void setNumber(String _number) {
		this.number = _number;
	}

	/**
	 * @return the _number
	 */
	public String getNumber() {
		return number;
	}

	/**
	 * @param _attendFlg
	 *            the _attendFlg to set
	 */
	public void setAttendFlg(int _attendFlg) {
		this.attendFlg = _attendFlg;
	}

	/**
	 * @return the _attendFlg
	 */
	public int getAttendFlg() {
		return attendFlg;
	}

	/**
	 * @param attendFlg
	 *            the _attendFlg to set
	 */
	public void setCameString(String val) {
		if (val.equals("-")) {
			attendFlg = ATTEND_FLG_NOT_SET;
		} else {
			attendFlg = ATTEND_FLG_REGISTERED;
		}
	}

	/**
	 * @param _comment
	 *            the _comment to set
	 */
	public void setComment(String _comment) {
		this.comment = _comment;
	}

	/**
	 * @return the _comment
	 */
	public String getComment() {
		return comment;
	}

	/*
	 * setter and getter
	 */

}
